package cn.edu.nju.ws.sview.servlets;

import java.io.IOException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;

import cn.edu.nju.ws.sview.cache.GroupNameIDCache;
import cn.edu.nju.ws.sview.cache.URIIDCache;
import cn.edu.nju.ws.sview.cache.UserNameIDCache;
import cn.edu.nju.ws.sview.cache.ViewCache;
import cn.edu.nju.ws.sview.views.Collaboration;
import cn.edu.nju.ws.sview.views.CustomDataMember;
import cn.edu.nju.ws.sview.views.DataMember;
import cn.edu.nju.ws.sview.views.URIDataMember;
import cn.edu.nju.ws.sview.views.View;

/**
 * Servlet implementation class TranslateServlet
 */
@WebServlet("/TranslateServlet")
public class TranslateServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	public static String STATUS_HasTransView = "hasTrans";
	public static String STATUS_REMOVED= "removed";
	public static String STATUS_SRC_REMOVED= "src_removed";
	public static String STATUS_OK= "ok";
	public static String STATUS_CONFLICT= "conflict";
	public static String STATUS_NOAUTHORITY= "noauthority";
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public TranslateServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		String option=null;
		String json=null;
		request.setCharacterEncoding("utf-8");
		response.setCharacterEncoding("utf-8");
		if(request.getParameter("transViewInit")!=null){
			json = request.getParameter("transViewInit");
			option = "transViewInit";
		}
		else if(request.getParameter("storetransview")!=null){
			json = request.getParameter("storetransview");
			option="storetransview";
		}
		
		if(option.equals("transViewInit")){
			String str = URLDecoder.decode(json,"utf-8");
			JSONObject regtJSON = (JSONObject) JSONValue.parse(str);
			int viewID = Integer.parseInt((String)regtJSON.get("vid"));
			//可能的已经翻译的view id
			int translatedViewID = Integer.parseInt((String)regtJSON.get("tvid"));
			String lang = View.getLanguage(viewID);
			
			JSONArray elements  = new JSONArray();
			JSONArray rmelements  = new JSONArray();
			
			ArrayList<DataMember> datamembers = View.getDataMembers(viewID) ;
			ArrayList<DataMember> transdatamembers = new ArrayList<DataMember>();
			
			if(translatedViewID>0){
				transdatamembers = View.getDataMembers(translatedViewID);
			}
			//表示被翻译的view中需要删除的datamember
			ArrayList<DataMember> removedDMs = new ArrayList<DataMember>(transdatamembers);
			removedDMs.removeAll(datamembers);
			
			try {
				for(DataMember datamember:datamembers){
					boolean isAdded = false;
					if(!transdatamembers.contains(datamember)){
						isAdded = true;
					}
					String originStr = null;
					JSONObject jsob = new JSONObject();
					int dmtype = 0;
					int dmid = 0;
					String name = null;
					int inverse = 0;
					int arity = 2;
					int functional = 0;
					int value_type = 0;
					
					if(datamember instanceof CustomDataMember){
						dmtype = DataMember.CUSTOM_DATAMEMBER;
						CustomDataMember cdm = (CustomDataMember) datamember;
						dmid  = cdm.getID();
					    name =  View.getLabelInView(viewID, dmtype, dmid);
						arity = cdm.getArity();
						functional = cdm.getFunctional()?1:0;
						value_type =cdm.getValueType();
						if(!isAdded){
							originStr = View.getLabelInView(translatedViewID, dmtype, dmid);
						}
					}else{
						dmtype = DataMember.URI_DATAMEMBER;
						URIDataMember udm = (URIDataMember) datamember;
						dmid =  udm.getID();
						name =  View.getLabelInView(viewID, dmtype, dmid);
						inverse =udm.isInverse()?1:0;
						functional = udm.getFunctional()?1:0;
						value_type = udm.getValueType() ;
						if(!isAdded){
							originStr = View.getLabelInView(translatedViewID, dmtype, dmid);
						}
					}
					
					jsob.put("dmtype", dmtype) ;
					jsob.put("dmid", dmid) ;
					jsob.put("name", name);
					jsob.put("inverse", inverse);
					jsob.put("arity", arity) ;
					jsob.put("vtype",value_type );
					jsob.put("functional", functional);
					jsob.put("isAdded",isAdded);
					jsob.put("originStr", originStr);
			        elements.add(jsob) ;
				}
				
				for(DataMember datamember:removedDMs){
					JSONObject jsob = new JSONObject();
					int dmtype = 0;
					int dmid = 0;
					String name = null;
					int inverse = 0;
					int arity = 2;
					int functional = 0;
					int value_type = 0;
					String originStr = null;
					
					if(datamember instanceof CustomDataMember){
						dmtype = DataMember.CUSTOM_DATAMEMBER;
						CustomDataMember cdm = (CustomDataMember) datamember;
						dmid  = cdm.getID();
					    name =  View.getLabelInView(translatedViewID, dmtype, dmid);
						arity = cdm.getArity();
						functional = cdm.getFunctional()?1:0;
						value_type =cdm.getValueType();
						originStr = View.getLabelInView(translatedViewID, dmtype, dmid);
					}else{
						dmtype = DataMember.URI_DATAMEMBER;
						URIDataMember udm = (URIDataMember) datamember;
						dmid =  udm.getID();
						name =  View.getLabelInView(translatedViewID, dmtype, dmid);
						inverse =udm.isInverse()?1:0;
						functional = udm.getFunctional()?1:0;
						value_type = udm.getValueType() ;
						originStr = View.getLabelInView(translatedViewID, dmtype, dmid);
					}
					
					jsob.put("dmtype", dmtype) ;
					jsob.put("dmid", dmid) ;
					jsob.put("name", name);
					jsob.put("inverse", inverse);
					jsob.put("arity", arity) ;
					jsob.put("vtype",value_type );
					jsob.put("functional", functional);
					jsob.put("originStr", originStr);
			        rmelements.add(jsob) ;
				}				
			} catch (Throwable e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			JSONObject result = new JSONObject();
			result.put("items",elements);
			result.put("removed", rmelements);
			response.getWriter().print(result) ;
		}else if(option.equals("storetransview")){
			JSONObject result = new JSONObject();
			/**
 			 * 返回值类型：jsonobject，
 			 * 其包含status:ok,noautority,conflict,removed,src_removed, has_trans
 			 * 并且当status=has_trans时返回已有的翻译的viewID
 			 */
			String str = URLDecoder.decode(json,"utf-8");
			JSONObject regtJSON = (JSONObject) JSONValue.parse(str);
			String name = (String)regtJSON.get("name") ;
			String user = (String)regtJSON.get("userName") ;
			int groupID = Integer.parseInt((String)regtJSON.get("groupID"));
			String lang = (String)regtJSON.get("viewLang") ;
			String group = null;
			try {
				group = GroupNameIDCache.getInstance().getName(groupID);
			} catch (Throwable e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			int viewId = Integer.parseInt((String)regtJSON.get("viewID"));
			int translatedViewID = Integer.parseInt((String)regtJSON.get("translatedViewID"));
			String userName = (String)regtJSON.get("userName");
			int userID = -1;
			try {
				userID = UserNameIDCache.getInstance().getUserID(userName);
			} catch (Throwable e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			boolean getAuthority = Collaboration.getInstance()
			.getEditAuthority(Collaboration.VIEW, translatedViewID, userID);
			if (getAuthority) {
				// 同步锁
				Object groupLock = Collaboration.getInstance()
						.getGroupProductLock(Collaboration.VIEW, groupID);
				
				// 判断以translatedViewID标识的View是否因协同编辑而在别处已被删除
				boolean isthere = true;
				if (translatedViewID > 0) {
					synchronized (groupLock) {
						isthere = View.isThere(translatedViewID);
					}
				}
				int existtransViewId = 0;
				if (!isthere) {
					Collaboration.getInstance().recoverAuthority(Collaboration.VIEW, translatedViewID);
					result.put("status", this.STATUS_REMOVED);
				} else if(!View.isThere(viewId)){
					Collaboration.getInstance().recoverAuthority(Collaboration.VIEW, translatedViewID);
					result.put("status", this.STATUS_SRC_REMOVED);
				} else if (translatedViewID<=0) {
					synchronized (groupLock) {
						existtransViewId = View.getTranlatedView(viewId);
					}
					if (existtransViewId > 0) {
						Collaboration.getInstance().recoverAuthority(
								Collaboration.VIEW, translatedViewID);
						result.put("status",
								TranslateServlet.STATUS_HasTransView);
						result.put("transvid", existtransViewId);
					}
				}
				else{
					int initialViewID = translatedViewID;
					boolean exist = false;
					
					synchronized (groupLock) {
						if (translatedViewID > 0) {
								int viewID = View.getViewIdByNameGroupClassID(
										name, group, View.isInner(viewId),
										View.getClassIDByViewID(viewId));
								if (viewID > 0&&viewID != translatedViewID) {
									exist = true;
								} 
								
								//在translatedViewID>0情况下，名字不冲突，赶紧存储
								//其它view就不能使用相同名字了
								if (!exist) {
									View view = View.getViewByViewId(translatedViewID);
									view.rename(name);
								}
						} else {
							int viewID = View.getViewIdByNameGroupClassID(name,
									group, View.isInner(viewId),
									View.getClassIDByViewID(viewId));
							if (viewID > 0) {
								exist = true;
							}
							
							if(!exist){
								//在viewID<=0情况下，名字不冲突，赶紧存储
								//由于在同步代码块内，其它view就不能使用相同名字了
								View view = new View(name,group,View.isInner(viewId),View.getClassURIStrByViewID(viewId),lang);
								view.serializeByTranslate(viewId) ;
								translatedViewID = view.getID();
							}
						}
					}
					
					if(!exist){
						//非同步代码块
						boolean isInner = View.isInner(translatedViewID);
						int classID = View.getClassIDByViewID(translatedViewID);
						/*add to favor views*/
						View.addFavorViewsForClassLangUser(translatedViewID, user,classID , lang,isInner);
						
						/*store view datamembers*/
						JSONArray  nameArray = (JSONArray)regtJSON.get("dmNames");
						ArrayList<DataMember> dms = new ArrayList<DataMember>();
						ArrayList<String> labels = new ArrayList<String>();
						for(int i=0;i<nameArray.size();i++){
							JSONObject dmObject = (JSONObject)nameArray.get(i);
						    String label = (String)dmObject.get("label");
						    int dmtype = Integer.parseInt((String)dmObject.get("dmtype"));
						    int dmid = Integer.parseInt((String)dmObject.get("dmid"));
						    boolean inverse = Integer.parseInt((String)dmObject.get("inverse"))==1?true:false;
						    if(dmtype==DataMember.CUSTOM_DATAMEMBER){
						    	DataMember dmDataMember = CustomDataMember.getCustomDataMemberById(dmid);
						    	dms.add(dmDataMember);
						    }else if(dmtype ==DataMember.URI_DATAMEMBER){
						    	String uri = null;
								try {
									uri = URIIDCache.getInstance().getURI(dmid);
								} catch (Throwable e) {
									// TODO Auto-generated catch block
									e.printStackTrace();
								}
						    	URIDataMember dmDataMember = new URIDataMember(uri);
						    	dmDataMember.setInverse(inverse);
						    	dms.add(dmDataMember);
						    }
						    labels.add(label);
						}
						
					    int viewID = View.getViewIdByNameGroupClassID(name, groupID, isInner, classID);
						if(viewID>0){
							View.serializeDataMembers(viewID, groupID, dms, labels)	;
						}
						
						/* update class-view cache */
						ViewCache.getInstance().addViewIntoCache(isInner, classID, translatedViewID, lang);
						
						/*store view reference*/
						try {
							HashSet<Integer> datamembers = View.getReferedCustomDataMemberIDs(translatedViewID);
							
							HashMap<Integer,Integer> referMap = new HashMap<Integer,Integer>();
							for(Integer datamemberID:datamembers){
								HashSet<Integer> set = CustomDataMember
										.getViewHasDataMember(datamemberID);
								for (Integer refvid : set) {
									if(refvid!=viewId){
										if (!referMap.containsKey(refvid)) {
											referMap.put(refvid, new Integer(0));
										}
										int count = referMap.get(refvid);
										count++;
										referMap.put(refvid, count);
									}
								}
							}
							View.storeReference(translatedViewID, referMap) ;
						}catch (Throwable e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
						
						//软件制品解锁
						Collaboration.getInstance().recoverAuthority(Collaboration.VIEW, initialViewID);
						result.put("status", this.STATUS_OK);
					}else {
						Collaboration.getInstance().recoverAuthority(
								Collaboration.VIEW, initialViewID);
						result.put("status", this.STATUS_CONFLICT);
					}
				}
			}else {
				//没有编辑权限，返回noauthority
				result.put("status", this.STATUS_NOAUTHORITY);
			}
			
			//最终返回结果
			response.getWriter().print(result);
		}
	}
}
